package com.atguigu.controller;

import com.atguigu.bean.Department;
import com.atguigu.bean.Employee;
import com.atguigu.dao.DepartmentDao;
import com.atguigu.dao.EmployeeDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.ImportResource;
import org.springframework.dao.support.DaoSupport;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;

/**
 * @author 伟哥
 * @date 2021-05-17 16:05
 */
@Controller
public class EmployeeController {

    @Autowired
    EmployeeDao employeeDao;

    @Autowired
    DepartmentDao departmentDao;

    /**
     * 处理首页index.jsp的 /emps请求
     *      请求方式：Get
     * @return 查询所有员工
     */
    @RequestMapping("/emps")
    public String getEmps(Model model){
        // 1、使用dao查询出所有的员工
        Collection<Employee> all = employeeDao.getAll();
        // 2、将信息存储在request域中，由页面展示
        model.addAttribute("emps",all);
        return "list";
    }

    /**
     * 增加员工：
     *      查询出所有的部门信息，用于页面展示
     * @param model
     * @return
     */
    @RequestMapping("/toAddPage")
    public String toAddPage(Model model){
        // 1、查询部门信息，用于回显
        Collection<Department> departments = departmentDao.getDepartments();
        model.addAttribute("depts",departments);
        /* 默认：提前在隐含模型中，添加command用于SpringMVC【表单标签】回显 */
        model.addAttribute("command",new Employee(null,"张三","123@123.com",1, new Date(), departmentDao.getDepartment(105)));

        /* 手动指定: deptDefault于SpringMVC的【表单标签】进行绑定，new 一个空的Employee对象*/
        model.addAttribute("employee",new Employee());
        return "add";
    }

    /**
     * 保存员工
     *      规定请求方式为：POST
     * @return
     */
    @RequestMapping(value = "/emp",method = RequestMethod.POST)
    public String addEmployee(@Valid Employee employee, BindingResult result,Model model,Locale locale){

        Properties properties = new Properties();
        // 使用ClassLoader加载properties配置文件生成对应的输入流
        InputStream in = null;
        if ("zh".equals(locale.getLanguage())){ //SpringMVC获取国际化：浏览器的语言设置
            // 中文浏览器读取，中文配置
            in = EmployeeController.class.getClassLoader().getResourceAsStream("errors_zh_CN.properties");
        }else {
            // 英文浏览器读取，英文配置
            in = EmployeeController.class.getClassLoader().getResourceAsStream("errors_en_US.properties");
        }
        // 使用properties对象加载输入流
        try {
            properties.load(in);
        } catch (IOException e) {
            e.printStackTrace();
        }




        System.out.println("要添加的员工："+employee);

        //原生页面API取出错误信息：1、创建map存储错误消息
        Map<String,String> errorMap = new HashMap<>();

        // 判断是否有校验错误
        boolean hasErrors = result.hasErrors();

        if (hasErrors){
            //原生页面API取出错误信息：2、遍历字段错误
            List<FieldError> fieldErrors = result.getFieldErrors();
            //打印这个整体的错误信息
            System.out.println(fieldErrors);

            for (FieldError error : fieldErrors) {
                /*
                原生页面API取出错误信息：3、在map中存储错误信息，
                    key是javaBean错误的属性名；value是错误消息，
                    这样前端就可以${errorInfo.birth}，取出错误消息
                 */
                //errorMap.put(error.getField(),error.getDefaultMessage());

                // 原生API:读取国际化信息
                switch (error.getField()){// 校验失败的属性名
                    case "lastName":
                        /*
                        1、errorMap的key是，校验失败的属性名
                        2、errorMap的value是，获取国际化配置文件中【key】，对应的【value】值：也就是获取国际化信息
                        2、存储在errorMap中
                         */
                        errorMap.put(error.getField(),properties.getProperty("Length.java.lang.String"));
                        break ;
                    case "email":
                        errorMap.put(error.getField(),properties.getProperty("Email.email"));
                        break ;
                    case "birth":
                        errorMap.put(error.getField(),properties.getProperty("Past"));
                        break ;
                    default:
                        System.out.println("参数有错误！");
                }
            }

            //原生页面API取出错误信息：4、把错误信息，存储在隐含模型中，key是errorInfo
            model.addAttribute("errorInfo",errorMap);
            //有错误，继续回到添加员工的页面add.jsp
            return "add";
        } else {
            // 存储员工
            employeeDao.save(employee);
        /*
         返回列表页面
         return "index";

            但是这样，来到index界面，会重新发送/emps
            这里我们，直接重定向，来到/emps
         */
            return "redirect:/emps";
        }
    }

    /**
     * 编辑Edit员工
     * @param id
     * @return
     */
    @RequestMapping(value = "/emp/{id}",method = RequestMethod.GET)
    public String getEmp(@PathVariable("id") Integer id,Model model){
        // 1、查出员工信息
        Employee employee = employeeDao.get(id);
        // 2、放在请求域中
        model.addAttribute("employee",employee);

        // 3、查询部门信息，放在隐含模型中，用来回显，edit页面的，部门下拉列表
        Collection<Department> departments = departmentDao.getDepartments();
        model.addAttribute("depts",departments);
        return "edit";
    }

    /**
     * 更新员工的方法
     * @param employee
     * @return
     */
    @RequestMapping(value = "/emp/{id}",method = RequestMethod.PUT)
    public String updateEmployee(@ModelAttribute("employee") Employee employee){
        System.out.println(employee);
        employeeDao.save(employee);
        return "redirect:/emps";
    }

    /**
     * 提前运行：查询员工
     */
    @ModelAttribute
    public void peekEmployee(@RequestParam(value = "id",required = false)Integer id,Model model){
        System.out.println("ModelAttribute标注的peekEmployee方法运行了...");
        if (id != null){
            Employee employee = employeeDao.get(id);
            model.addAttribute("employee",employee);
        }

        // 查询部门信息，放在隐含模型中，用来回显，edit页面、add页面的，部门下拉列表
        Collection<Department> departments = departmentDao.getDepartments();
        model.addAttribute("depts",departments);
    }

    /**
     * 删除员工
     */
    @RequestMapping(value = "/emp/{id}",method = RequestMethod.DELETE)
    public String deleteEmploy(@PathVariable("id") Integer id){
        employeeDao.delete(id);

        return "redirect:/emps";
    }

    /**
     * 数据绑定：
     *
     * 发送请求带的数据是什么？
     *      （1）默认，获取不到
     *      前端带的是quickAdd?quickAddEmployee=empAdmin-admin@qq.com-1-101
     *
     *
     *      （2）告知Spring转换：异常
     *      告诉SpringMVC，@RequestParam("quickAddEmployee") Employee employee
     *      Employee employee = request.getParameter("quickAddEmployee");
     *          这当然是不行的，request.getParameter("quickAddEmployee");获取的是前端的【字符串】！！
     *          不能转换为后端的JavaBean：Employee,会出现异常！
     *          异常信息：no matching editors or conversion strategy found
     *
     *      （3）自定义类型转换器，让其工作
     *      所以，类型转换，是SpringMVC中的各种类型转换器在工作，可以把各种前端的String转为java数据类型。
     *      但是，没有把String转为Employee类型的转换器，接下来我们就写一个，把String转为Employee类型的转换器
     * @param employee
     * @return
     */
    @RequestMapping("/quickAdd")
    public String quickEmploy(@RequestParam("quickAddEmployee") Employee employee){
        System.out.println("SpringMVC封装的对象是："+employee);
        //SpringMVC封装的对象是：Employee [id=null, lastName=null, email=null, gender=null, department=null]
        employeeDao.save(employee);
        return "redirect:/emps";
    }
}
